package com.angola.sms.network

import android.util.Log
import okhttp3.*
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit

object ServiceCreator {

    private val mLoggingInterceptor: HttpLoggingInterceptor =
        HttpLoggingInterceptor(ResponseLogger()).apply {
            this.level = HttpLoggingInterceptor.Level.BODY
        }

    private val retrofit =
        Retrofit.Builder()
            .baseUrl(NetReqUrl.BASE_URL)
            .client(getHttpClient())
            .addConverterFactory(GsonConverterFactory.create())
            .build()

    private fun getHttpClient(): OkHttpClient {
        return OkHttpClient.Builder()
            .connectTimeout(60, TimeUnit.SECONDS)
            .writeTimeout(60, TimeUnit.SECONDS)
            .readTimeout(60, TimeUnit.SECONDS)
            .retryOnConnectionFailure(true)
            .connectionPool(ConnectionPool(5, 3, TimeUnit.MINUTES))
            .protocols(listOf(Protocol.HTTP_1_1))
            .addNetworkInterceptor(mLoggingInterceptor)
            .build()
    }

    fun <T> create(serviceClass: Class<T>): T = retrofit.create(serviceClass)

    inline fun <reified T> create(): T = create(T::class.java)
}

class ResponseInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val request: Request = chain.request()
//        Log.d(ResponseInterceptor::class.java.simpleName, "Url: " + request.url)
//        Log.d(ResponseInterceptor::class.java.simpleName, "body: " + request.body)

        val builder: Request.Builder = request.newBuilder()
        val targetRequest: Request = builder.build()
        return chain.proceed(targetRequest)
    }
}

class ResponseLogger : HttpLoggingInterceptor.Logger {
    override fun log(message: String) {
        if (message.length > 4000) {
            var i = 0
            while (i < message.length) {
                if (i + 4000 < message.length) {
                    Log.i(ResponseLogger::class.java.simpleName + i,
                        formatJson(message.substring(i, i + 4000)))
                } else {
                    Log.i(ResponseLogger::class.java.simpleName + i,
                        formatJson(message.substring(i, message.length)))
                }
                i += 4000
            }
        } else {
            Log.i(ResponseLogger::class.java.simpleName, formatJson(message))
        }
    }

    private fun formatJson(jsonStr: String): String {
        var level = 0
        val jsonForMatStr = StringBuffer()
        for (element in jsonStr) {
            val c = element
            if (level > 0 && '\n' == jsonForMatStr[jsonForMatStr.length - 1]) {
                jsonForMatStr.append(getLevelStr(
                    level))
            }
            when (c) {
                '{', '[' -> {
                    jsonForMatStr.append("${c}\n")
                    level++
                }
                ',' -> {
                    jsonForMatStr.append("${c}\n")
                }
                '}', ']' -> {
                    jsonForMatStr.append("\n")
                    level--
                    jsonForMatStr.append(getLevelStr(level))
                    jsonForMatStr.append(c)
                }
                else -> jsonForMatStr.append(c)
            }
        }
        return jsonForMatStr.toString()
    }

    private fun getLevelStr(level: Int): String {
        val levelStr = StringBuffer()
        for (levelI in 0 until level) {
            levelStr.append("\t")
        }
        return levelStr.toString()
    }
}
